package cn.loioi.web.components.servlet;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 验证码生成器
 * @文件 :VerifyCodeServlet.java
 * @作者 :cn.loioi
 * @创建时间 :2016年10月13日 下午1:15:46
 */
public class VerifyCodeServlet extends HttpServlet {
	private static final long serialVersionUID = 3038623696184546092L;
	private static final int MODE = 0;// 组合模式：0-数字字母混合；1-纯数字；2-纯字母
	private static final int LENGTH = 4; // 字数
	private static final String VALUE_NUM = "23456789"; // 候选词-数字
	private static final String VALUE_LETTER = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz";// 候选词-字母
	private int width = 100;// 图片宽度
	private int height = 35;// 图片高度
	private String sessionParam = "verify_code"; // 生成结果存session的参数名

	/**
	 * 初始化
	 * @param width 图片宽度
	 * @param height 图片高度
	 */
	@Override
	public void init(ServletConfig config) throws ServletException {
		try {
			String readWidth = config.getInitParameter("width");
			String readHeight = config.getInitParameter("height");
			String readSessionParam = config.getInitParameter("sessionParam");

			width = (readWidth == null || readWidth.isEmpty()) ? width : Integer.parseInt(readWidth);
			height = (readHeight == null || readHeight.isEmpty()) ? height : Integer.parseInt(readHeight);
			sessionParam = (readSessionParam == null || readSessionParam.isEmpty()) ? sessionParam : readSessionParam;

		} catch (Exception e) {
		}
	}

	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		// 1.获取图形上下文,graphics想象成一个画笔
		Graphics2D graphics = (Graphics2D) image.getGraphics();
		// 2.设置背景色
		graphics.setColor(Color.WHITE);// 设置颜色
		graphics.fillRect(0, 0, width, height);// 填充区域
		// 3.设置边框
		graphics.setColor(Color.WHITE);// 设置颜色
		graphics.drawRect(1, 1, width - 2, height - 2);// 填充区域
		// 4.画随机线
		drawRandomLine(graphics);
		// 5.生成验证码
		String random = drawRandomString(graphics).toLowerCase();
		// 6.关闭Graphics2D，释放系统资源
		graphics.dispose();
		// 6.将验证码存在session中
		request.getSession().setAttribute(sessionParam, random);
		// 7.设置响应头，控制浏览器不要缓存
		response.setContentType("image/jpeg");
		response.setDateHeader("expries", -1);
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "no-cache");
		// 8.将图片写给浏览器
		ImageIO.write(image, "jpg", response.getOutputStream());
	}

	/**
	 * 在图片上画5条随机线条
	 * @param graphics
	 */
	private void drawRandomLine(Graphics2D graphics) {
		// 设置颜色
		graphics.setColor(Color.GREEN);
		// 设置线条个数并画线
		for (int i = 0; i < 5; i++) {
			int x1 = new Random().nextInt(width);
			int y1 = new Random().nextInt(height);
			int x2 = new Random().nextInt(width);
			int y2 = new Random().nextInt(height);
			graphics.drawLine(x1, y1, x2, y2);
		}
	}

	/**
	 * 画随机字符
	 * @param graphics
	 * @return 随机字符
	 */
	private String drawRandomString(Graphics2D graphics) {
		graphics.setColor(Color.RED); // 设置颜色
		graphics.setFont(new Font("宋体", Font.BOLD, 25));// 设置字体
		switch (MODE) {
		case 1:
			return createRandomChar(graphics, VALUE_NUM);
		case 2:
			return createRandomChar(graphics, VALUE_LETTER);
		default:
			return createRandomChar(graphics, VALUE_LETTER + VALUE_NUM);
		}
	}

	/**
	 * 创建随机字符
	 * @param graphics
	 * @param str
	 * @return 随机字符
	 */
	private String createRandomChar(Graphics2D graphics, String str) {
		StringBuffer sb = new StringBuffer();
		int x = (width / LENGTH);
		for (int i = 0; i < LENGTH; i++) {
			// 设置字体旋转角度
			int degree = new Random().nextInt() % 30;
			String ch = str.charAt(new Random().nextInt(str.length())) + "";
			sb.append(ch);
			graphics.rotate(degree * Math.PI / 180, (i * x) + 5, 30);
			graphics.drawString(ch, (i * x) + 5, 30);
			graphics.rotate(-degree * Math.PI / 180, (i * x) + 5, 30);
		}
		return sb.toString();
	}
}
